#include "stdafx.h"

#define SRC_ID 3
#define P1_ID 4
#define C1_ID 5
#define DST_ID 6

#define AS1_ID 7
#define AS2_ID 8
#define TRICKED_ID 9

#define AS702_ID 702
#define AS43284_ID 43284
#define AS13030_ID 13030
#define AS13030_1_ID 13031
#define AS702_1_ID 703
#define AS702_2_ID 704
#define AS702_3_ID 705
#define AS702_4_ID 706

#define AS25653_ID 25653
#define AS4436_ID 4436
#define AS852_ID 852
#define AS3561_ID 3561
#define AS209_ID 209
#define AS721_ID 721
#define AS27064_ID 27064
#define AS27085_ID 27085
#define AS3561_1_ID 3562
#define AS3561_2_ID 3563
#define AS3561_3_ID 3564
#define AS3561_4_ID 3565



//============================================================================
// Name        : BgpSecurity_Svn.cpp
// Author      : Nirram
// Version     :
// Copyright   : 
// Description : Hello World in C++, Ansi-style
//============================================================================

//#include <tchar.h>
//#include <iostream>

#include "Edge.h"
#include "Vertex.h"
#include "Graph.h"
#include "Topology.h"
#include "AttackerAs.h"
#include "Attack.h"
#include "SPEA.h"
#include "SpeaWithConnectivity.h"
#include "ExpliSatConverter.h"
#include "BgpMessage.h"

//  As.UpdateOnRcvSelectedPathsFromNeighbor Unit Testing

void TestProviderAndThenCustomer() {
	// G:
	//      Dest
	//     ^   |
	//     |   v
	//     p1  c1
	//     ^   |
	//     |   v
	//      src
	//
	Topology g = Topology();

//  Prepare Vertices

	As src = As(SRC_ID);
	As p1 = As(P1_ID);
	As c1 = As(C1_ID);
	As dst = As(DST_ID);

	As *srcp = &src;
	As *p1p = &p1;
	As *c1p = &c1;
	As *dstp = &dst;

// -------------

//  Prepare Edges

	g.InsertCustomerProvider(srcp, p1p);
	g.InsertCustomerProvider(p1p, dstp);

	g.InsertCustomerProvider(c1p, srcp);
	g.InsertCustomerProvider(dstp, c1p);

// -------------

	g.PrintGraph();

//  Providers Path

	Map<As*, Vector<As*> > providerPaths = Map<As*, Vector<As*> >();
	Map<As*, Vector<As*> >* providerPathsPointer = &providerPaths;
	Vector<As*> providerPath = Vector<As*>();
	providerPath.push_back(dstp);
	providerPathsPointer->insert(Pair<As*, Vector<As*> >(dstp, providerPath));

	BgpMessage providersMsg = BgpMessage(providerPathsPointer);
	src.UpdateOnRcvSelectedPathsFromNeighbor(p1p, providersMsg);

// -------------

//  Customers Path

	Map<As*, Vector<As*> > customerPaths = Map<As*, Vector<As*> >();
	Map<As*, Vector<As*> >* customerPathsPointer = &customerPaths;
	Vector<As*> customerPath = Vector<As*>();
	customerPath.push_back(dstp);
	customerPathsPointer->insert(Pair<As*, Vector<As*> >(dstp, customerPath));

	BgpMessage customersMsg = BgpMessage(customerPathsPointer);
	src.UpdateOnRcvSelectedPathsFromNeighbor(c1p, customersMsg);

	// Expected Result = The path through the c1p to dst should be selected, i.e. an update should occure
// -------------
}

void TestCustomerAndThenProvider() {
	// G:
	//      Dest
	//     ^   |
	//     |   v
	//     p1  c1
	//     ^   |
	//     |   v
	//      src
	//
	Topology g = Topology();

//  Prepare Vertices

	As src = As(SRC_ID);
	As p1 = As(P1_ID);
	As c1 = As(C1_ID);
	As dst = As(DST_ID);

	As *srcp = &src;
	As *p1p = &p1;
	As *c1p = &c1;
	As *dstp = &dst;

// -------------

//  Prepare Edges

	g.InsertCustomerProvider(srcp, p1p);
	g.InsertCustomerProvider(p1p, dstp);

	g.InsertCustomerProvider(c1p, srcp);
	g.InsertCustomerProvider(dstp, c1p);

// -------------

	g.PrintGraph();

//  Customers Path

	Map<As*, Vector<As*> > customerPaths = Map<As*, Vector<As*> >();
	Map<As*, Vector<As*> >* customerPathsPointer = &customerPaths;
	Vector<As*> customerPath = Vector<As*>();
	customerPath.push_back(dstp);
	customerPathsPointer->insert(Pair<As*, Vector<As*> >(dstp, customerPath));

	BgpMessage customersMsg = BgpMessage(customerPathsPointer);
	src.UpdateOnRcvSelectedPathsFromNeighbor(c1p, customersMsg);

// -------------

//  Providers Path

	Map<As*, Vector<As*> > providerPaths = Map<As*, Vector<As*> >();
	Map<As*, Vector<As*> >* providerPathsPointer = &providerPaths;
	Vector<As*> providerPath = Vector<As*>();
	providerPath.push_back(dstp);
	providerPathsPointer->insert(Pair<As*, Vector<As*> >(dstp, providerPath));

	// Expected Result = The path through the c1p to dst should be selected, i.e. no update should occure
	// And src.WasUpdateOnSelectedPaths should be false

	BgpMessage providersMsg = BgpMessage(providerPathsPointer);
	src.UpdateOnRcvSelectedPathsFromNeighbor(p1p, providersMsg);

// -------------
}

// -------------

//  As.RunBgp Unit Testing

void TestBgpRunWithTwoAss() {
	// G:
	//       c1
	//        |
	//        v
	//      src
	//
	Topology g = Topology();

	//  Prepare Vertices

	As src = As(SRC_ID);
	As c1 = As(C1_ID);

	As *srcp = &src;
	As *c1p = &c1;

	// -------------

	//  Prepare Edges

	g.InsertCustomerProvider(c1p, srcp);

	// -------------

	//g.PrintGraph();
	g.RunBgp();
	g.PrintSelectedaPaths();

	// Expected Result =
	// After Bgp the source path to Dest should be:
	//       c1
	//       |
	//       v
	//      src
	//
}

void TestBgpRunWithThreeAss() {
	// G:
	//    p1 -> c1
	//     ^    |
	//     |    v
	//       src
	//
	Topology g = Topology();

//  Prepare Vertices

	As src = As(SRC_ID);
	As c1 = As(C1_ID);
	As p1 = As(P1_ID);

	As *srcp = &src;
	As *c1p = &c1;
	As *p1p = &p1;

// -------------

//  Prepare Edges

	g.InsertCustomerProvider(srcp, p1p);
	g.InsertCustomerProvider(p1p, c1p);
	g.InsertCustomerProvider(c1p, srcp);

// -------------

	//g.PrintGraph();
	g.RunBgp();
	g.PrintSelectedaPaths();

	// Expected Result =
	// After Bgp the source path to Dest should be:
	//    p1 -> c1
	//          |
	//          v
	//       src
	//
}

void TestBgpRunWithProviderAndConsumerPaths() {
	// G:
	//      Dest
	//     ^   |
	//     |   v
	//     p1  c1
	//     ^   |
	//     |   v
	//      src
	//
	Topology g = Topology();

//  Prepare Vertices

	As src = As(SRC_ID);
	As p1 = As(P1_ID);
	As c1 = As(C1_ID);
	As dst = As(DST_ID);

	As *srcp = &src;
	As *p1p = &p1;
	As *c1p = &c1;
	As *dstp = &dst;

// -------------

//  Prepare Edges

	g.InsertCustomerProvider(srcp, p1p);
	g.InsertCustomerProvider(p1p, dstp);

	g.InsertCustomerProvider(c1p, srcp);
	g.InsertCustomerProvider(dstp, c1p);

// -------------

	//g.PrintGraph();
	g.RunBgp();
	g.PrintSelectedaPaths();
	// Expected Result =
	// After Bgp the source path to Dest should be:
	//      Dest
	//         |
	//         v
	//     p1  c1
	//         |
	//         v
	//      src
	//
}

// -------------

//  SpeaWithConnectivity.Compute Shortest path Unit testing

//void TestSPEAConnectivity_ShortersPathTest() {
//	// G:
//	//                 victim
//	//                  |
//	//                  v
//	//                  as2
//	//                  |
//	//                  v
//	//                  as1
//	//Path length = 2   |     ^
//	//                  v      \
//				//                 Tricked <-- Attacker
//	//                      Path length = 3
//	// Result Path should be " Attacker, as1, as2, victim"
//	//
//	Topology g = Topology();
//
////  Prepare Vertices
//
//	As victim = As(VICTIM_ID);
//	As as1 = As(AS1_ID);
//	As as2 = As(AS2_ID);
//	As tricked = As(TRICKED_ID);
//	AttackerAs attacker = AttackerAs();
//
//// -------------
//
////  Prepare Edges
//
//	g.InsertCustomerProvider(&victim, &as2);
//	g.InsertCustomerProvider(&as2, &as1);
//	g.InsertCustomerProvider(&as1, &tricked);
//	g.InsertCustomerProvider(&attacker, &tricked);
//	g.InsertCustomerProvider(&attacker, &as1);
//
//// -------------
//
////  Prepare Attack
//
//	SpeaWithConnectivity spea = SpeaWithConnectivity(&g, &victim, &attacker);
//	attacker.TheAttack = &spea;
//
//// -------------
//
//	Map<Vertex*, SpeaWithConnectivity::weight_t> * min_distance = new Map<Vertex*, SpeaWithConnectivity::weight_t>();
//	Map<Vertex*, Vertex*> *previous = new Map<Vertex*, Vertex*>();
//
//	spea.DijkstraComputePaths(&attacker, min_distance, previous);
//
//	//std::cout << "Distance from attacker to victim: " << min_distance->at(&victim) << std::endl;
//	Vector<As*> path = spea.DijkstraGetShortestPathTo(&victim, previous);
//	//std::cout << "Path : ";
//	//for (unsigned int i = 0; i < path.size(); i++) {
//	//	std::cout << path[i]->GetName() << ", ";
//	//}
//	//std::cout << std::endl;
//
//	// Result Path should be " as1, as2, victim"
//}

// -------------

//  Attacks

//  Intuitive Attacks

void TestBgpWithoutAttacks() {
	// G:
	//      Dest
	//     ^   |
	//     |   v
	//     p1  c1
	//     ^   |
	//     |   v
	//      src
	//
	Topology g = Topology();

//  Prepare Vertices

	As src = As(SRC_ID);
	As p1 = As(P1_ID);
	As c1 = As(C1_ID);
	As dst = As(DST_ID);

	As *srcp = &src;
	As *p1p = &p1;
	As *c1p = &c1;
	As *dstp = &dst;

// -------------

//  Prepare Edges

	g.InsertCustomerProvider(srcp, p1p);
	g.InsertCustomerProvider(p1p, dstp);

	g.InsertCustomerProvider(c1p, srcp);
	g.InsertCustomerProvider(dstp, c1p);

// -------------

	g.PrintGraph();
	g.RunBgp();
	g.PrintSelectedaPaths();

	As* attacker = srcp;
	//As* attacker = c1p;
	//As* attacker = p1p;
	As* victim = dstp;

	//std::cout << "Number of paths to the victim(" << victim->GetName() << ") through the attacker(" << attacker->GetName() << ") is "
	//		<< g.HowMuchTrafficThroughTheAttacker(attacker, victim) << std::endl;
	// Expected Result = <<attacker(result)> > - c1(2), src(1), p1(0)
}

void TestBgpWithSPEA_2Ass() {
	// G:
	//     Attacker
	//        |
	//        v
	//     Victim
	//
	Topology g = Topology();

	//  Prepare Vertices

	As victim = As(VICTIM_ID);
	AttackerAs attacker = AttackerAs();

	// -------------

	//  Prepare Edges

	g.InsertCustomerProvider(&attacker, &victim);

	// -------------

	//  Prepare Attack

	Attack spea = SPEA(&g, &victim, &attacker);
	attacker.TheAttack = &spea;

	// -------------

	g.PrintGraph();
	g.RunBgp();
	g.PrintSelectedaPaths();

		//std::cout << "Number of paths to the victim(" << victim.GetName() << ") through the attacker(" << attacker.GetName() << ") is "
		//		<< g.HowMuchTrafficThroughTheAttacker(&attacker, &victim) << std::endl;
}

void TestBgpWithSPEA_SmallestNetwork_3ass() {
	// G:
	//     Victim
	//        ^
	//        |
	//     Tricked <- Attacker
	//
	Topology g = Topology();

//  Prepare Vertices

	As victim = As(VICTIM_ID);
	As tricked = As(TRICKED_ID);
	AttackerAs attacker = AttackerAs();

// -------------

//  Prepare Edges

	g.InsertCustomerProvider(&tricked, &victim);
	g.InsertCustomerProvider(&attacker, &tricked);

// -------------

//  Prepare Attack

	Attack spea = SPEA(&g, &victim, &attacker);
	attacker.TheAttack = &spea;

// -------------

	g.PrintGraph();
	g.RunBgp();
	g.PrintSelectedaPaths();

	//std::cout << "Number of paths to the victim(" << victim.GetName() << ") through the attacker(" << attacker.GetName() << ") is "
	//		<< g.HowMuchTrafficThroughTheAttacker(&attacker, &victim) << std::endl;
}

void TestBgpWithSPEA_TopologyThatItIsEffective() {
	// G:
	//                 victim
	//                  |
	//                  v
	//                  as2
	//                  |
	//                  v
	//                  as1
	//Path length = 2   |     ^
	//                  v      \
							//                 Tricked <-- Attacker
	//                      Path length = 3
	//
	// Will look like this:
	//
	// G:
	//                 victim  <-----|
	//                  |            |
	//                  v            |
	//                  as2          |
	//                  |            |
	//                  v            |
	//                  as1          |
	//Path length = 2   |            |
	//                  v            |
	//                 Tricked <-- Attacker
	//                      Path length = 1
	//
	Topology g = Topology();

//  Prepare Vertices

	As victim = As(VICTIM_ID);
	As as1 = As(AS1_ID);
	As as2 = As(AS2_ID);
	As tricked = As(TRICKED_ID);
	AttackerAs attacker = AttackerAs();

// -------------

//  Prepare Edges

	g.InsertCustomerProvider(&victim, &as2);
	g.InsertCustomerProvider(&as2, &as1);
	g.InsertCustomerProvider(&as1, &tricked);
	g.InsertCustomerProvider(&attacker, &tricked);
	g.InsertCustomerProvider(&attacker, &as1);

// -------------

//  Prepare Attack

	Attack spea = SPEA(&g, &victim, &attacker);
	attacker.TheAttack = &spea;

// -------------

	g.PrintGraph();
	g.RunBgp();
	g.PrintSelectedaPaths();

	//std::cout << "Number of paths to the victim(" << victim.GetName() << ") through the attacker(" << attacker.GetName() << ") is "
	//		<< g.HowMuchTrafficThroughTheAttacker(&attacker, &victim) << std::endl;
	// Expected Result = <<attacker(result)> > - c1(2), src(1), p1(0)
}

// -------------

//  Smart Attacks

void TestBgpWithSPEA_SmartTopologyAnnounceLongerPaths() 
{
	// SPEA Attack
	{
		// G:
		//                 victim  -- |
		//                  |       13030
		//                  |         ^
		//                  702       |
		//                  ^       43284
		//                  |         ^
		//                 Attacker __|
		//
		//
		Topology g = Topology();

//  Prepare Vertices

		As victim = As(VICTIM_ID);
		As as702 = As(AS702_ID);
		As as43284 = As(AS43284_ID);
		As as13030 = As(AS13030_ID);
		AttackerAs attacker = AttackerAs();

		As as13030_1 = As(AS13030_1_ID);
		As as702_1 = As(AS702_1_ID);
		As as702_2 = As(AS702_2_ID);
		As as702_3 = As(AS702_3_ID);
		As as702_4 = As(AS702_4_ID);

// -------------

//  Prepare Edges

		g.InsertCustomerProvider(&attacker, &as702);
		g.InsertPeerToPeer(&as702, &victim);
		g.InsertCustomerProvider(&attacker, &as43284);
		g.InsertCustomerProvider(&as43284, &as13030);
		g.InsertPeerToPeer(&as13030, &victim);

		g.InsertCustomerProvider(&as13030_1, &as13030);

		g.InsertCustomerProvider(&as702_1, &as702);
		g.InsertCustomerProvider(&as702_2, &as702);
		g.InsertCustomerProvider(&as702_3, &as702);
		g.InsertCustomerProvider(&as702_4, &as702);

// -------------

//  Prepare Attack

		Map<As*, Vector<As*> > pathToVictim = Map<As*, Vector<As*> >();

		Vector<As*> selfPath = Vector<As*>();
		selfPath.push_back(&as702);
		selfPath.push_back(&victim);
		pathToVictim.insert(Pair<As*, Vector<As*> >(&victim, selfPath));
		BgpMessage msg = BgpMessage(&pathToVictim);

		Set<As*> whoToSend = Set<As*>();
		// whoToSend.insert(&as702);
		whoToSend.insert(&as43284);

		Attack spea = Attack(&msg, &whoToSend);
		attacker.TheAttack = &spea;

// -------------

		//g.PrintGraph();
		g.RunBgp();
		//g.PrintSelectedaPaths();

		//std::cout << "SPEA - Number of paths to the victim(" << victim.GetName() << ") through the attacker(" << attacker.GetName() << ") is "
		//		<< g.HowMuchTrafficThroughTheAttacker(&attacker, &victim) << std::endl;
		// Expected Result = 2
	}

	// G:
	//                 victim  -- |
	//                  |       13030
	//                  |         ^
	//                  702       |
	//                  ^       43284
	//                  |         ^
	//                 Attacker __|
	//
	//

	// Smart Attack - Export Longer Path
	{
		Topology g = Topology();

//  Prepare Vertices

		As victim = As(VICTIM_ID);
		As as702 = As(AS702_ID);
		As as43284 = As(AS43284_ID);
		As as13030 = As(AS13030_ID);
		AttackerAs attacker = AttackerAs();

		As as13030_1 = As(AS13030_1_ID);
		As as702_1 = As(AS702_1_ID);
		As as702_2 = As(AS702_2_ID);
		As as702_3 = As(AS702_3_ID);
		As as702_4 = As(AS702_4_ID);

// -------------

//  Prepare Edges

		g.InsertCustomerProvider(&attacker, &as702);
		g.InsertPeerToPeer(&as702, &victim);
		g.InsertCustomerProvider(&attacker, &as43284);
		g.InsertCustomerProvider(&as43284, &as13030);
		g.InsertPeerToPeer(&as13030, &victim);

		g.InsertCustomerProvider(&as13030_1, &as13030);

		g.InsertCustomerProvider(&as702_1, &as702);
		g.InsertCustomerProvider(&as702_2, &as702);
		g.InsertCustomerProvider(&as702_3, &as702);
		g.InsertCustomerProvider(&as702_4, &as702);

// -------------

//  Prepare Attack

		Map<As*, Vector<As*> > pathToVictim = Map<As*, Vector<As*> >();

		Vector<As*> selfPath = Vector<As*>();
		selfPath.push_back(&as43284);
		selfPath.push_back(&as13030);
		selfPath.push_back(&victim);
		pathToVictim.insert(Pair<As*, Vector<As*> >(&victim, selfPath));
		BgpMessage msg = BgpMessage(&pathToVictim);

		Set<As*> whoToSend = Set<As*>();
		whoToSend.insert(&as702);
		//whoToSend.insert(&as43284);

		Attack spea = Attack(&msg, &whoToSend);
		attacker.TheAttack = &spea;

// -------------

		//g.PrintGraph();
		g.RunBgp();
		g.PrintSelectedaPaths();

		//std::cout << "Smart Attack (Longer Paths) - Number of paths to the victim(" << victim.GetName() << ") through the attacker(" << attacker.GetName()
		//		<< ") is " << g.HowMuchTrafficThroughTheAttacker(&attacker, &victim) << std::endl;
		// Expected Result = 1
	}
}

//#include <iostream>
void TestBgpWithSpeaWithConnectivity_SmartTopologyAnnounceLongerPaths() {
	// SPEA with connectivity Attack
	{
		// G:
		//                 victim  -- |
		//                  |       13030
		//                  |         ^
		//                  702       |
		//                  ^       43284
		//                  |         ^
		//                 Attacker __|
		//
		//
		Topology g = Topology();

//  Prepare Vertices

		As victim = As(VICTIM_ID);
		As as702 = As(AS702_ID);
		As as43284 = As(AS43284_ID);
		As as13030 = As(AS13030_ID);
		AttackerAs attacker = AttackerAs();

		As as13030_1 = As(AS13030_1_ID);
		As as702_1 = As(AS702_1_ID);
		As as702_2 = As(AS702_2_ID);
		As as702_3 = As(AS702_3_ID);
		As as702_4 = As(AS702_4_ID);

// -------------

//  Prepare Edges

		g.InsertCustomerProvider(&attacker, &as702);
		g.InsertPeerToPeer(&as702, &victim);
		g.InsertCustomerProvider(&attacker, &as43284);
		g.InsertCustomerProvider(&as43284, &as13030);
		g.InsertPeerToPeer(&as13030, &victim);

		g.InsertCustomerProvider(&as13030_1, &as13030);

		g.InsertCustomerProvider(&as702_1, &as702);
		g.InsertCustomerProvider(&as702_2, &as702);
		g.InsertCustomerProvider(&as702_3, &as702);
		g.InsertCustomerProvider(&as702_4, &as702);

// -------------

//  Prepare Attack

		SpeaWithConnectivity spea = SpeaWithConnectivity(&g, &victim, &attacker);
		attacker.TheAttack = &spea;

// -------------

		//g.PrintGraph();
		g.RunBgp();
		//g.PrintSelectedaPaths();

		//std::cout << "SPEA with connectivity- Number of paths to the victim(" << victim.GetName() << ") through the attacker(" << attacker.GetName() << ") is "
		//		<< g.HowMuchTrafficThroughTheAttacker(&attacker, &victim) << std::endl;
		// Expected Result = 2
	}

	// G:
	//                 victim  -- |
	//                  |       13030
	//                  |         ^
	//                  702       |
	//                  ^       43284
	//                  |         ^
	//                 Attacker __|
	//
	//

	// Smart Attack - Export Longer Path
	{
		Topology g = Topology();

//  Prepare Vertices

		As victim = As(VICTIM_ID);
		As as702 = As(AS702_ID);
		As as43284 = As(AS43284_ID);
		As as13030 = As(AS13030_ID);
		AttackerAs attacker = AttackerAs();

		As as13030_1 = As(AS13030_1_ID);
		As as702_1 = As(AS702_1_ID);
		As as702_2 = As(AS702_2_ID);
		As as702_3 = As(AS702_3_ID);
		As as702_4 = As(AS702_4_ID);

// -------------

//  Prepare Edges

		g.InsertCustomerProvider(&attacker, &as702);
		g.InsertPeerToPeer(&as702, &victim);
		g.InsertCustomerProvider(&attacker, &as43284);
		g.InsertCustomerProvider(&as43284, &as13030);
		g.InsertPeerToPeer(&as13030, &victim);

		g.InsertCustomerProvider(&as13030_1, &as13030);

		g.InsertCustomerProvider(&as702_1, &as702);
		g.InsertCustomerProvider(&as702_2, &as702);
		g.InsertCustomerProvider(&as702_3, &as702);
		g.InsertCustomerProvider(&as702_4, &as702);

// -------------

//  Prepare Attack

		Map<As*, Vector<As*> > pathToVictim = Map<As*, Vector<As*> >();

		Vector<As*> selfPath = Vector<As*>();
		selfPath.push_back(&as43284);
		selfPath.push_back(&as13030);
		selfPath.push_back(&victim);
		pathToVictim[&victim] = selfPath;
		BgpMessage msg = BgpMessage(&pathToVictim);

		Set<As*> whoToSend = Set<As*>();
		whoToSend.insert(&as702);
		//whoToSend.insert(&as43284);

		Attack spea = Attack(&msg, &whoToSend);
		attacker.TheAttack = &spea;

// -------------

		//g.PrintGraph();
		g.RunBgp();
		//g.PrintSelectedaPaths();

		//std::cout << "Smart Attack (Longer Paths) - Number of paths to the victim(" << victim.GetName() << ") through the attacker(" << attacker.GetName()
		//		<< ") is " << g.HowMuchTrafficThroughTheAttacker(&attacker, &victim) << std::endl;
		// Expected Result = 1
	}
}

// -------------

// -------------

#include <iostream>
void Test_ExpicitSatConverterOld() 
{
	// SPEA with connectivity Attack
	{
		// G:
		//                 victim  -- |
		//                  |       13030
		//                  |         ^
		//                  702       |
		//                  ^       43284
		//                  |         ^
		//                 Attacker __|
		//
		//
		Topology g = Topology();
		Vector<As*>* orderedAss = new Vector<As*>();

//  Prepare Vertices

		As victim = As(VICTIM_ID);
		As as702 = As(AS702_ID);
		As as43284 = As(AS43284_ID);
		As as13030 = As(AS13030_ID);
		AttackerAs attacker = AttackerAs();

		// Extend
		As as13030_1 = As(AS13030_1_ID);
		As as702_1 = As(AS702_1_ID);
		As as702_2 = As(AS702_2_ID);
		As as702_3 = As(AS702_3_ID);
		As as702_4 = As(AS702_4_ID);

// -------------

//  Prepare Edges

		g.InsertCustomerProvider(&attacker, &as702);
		g.InsertPeerToPeer(&as702, &victim);
		g.InsertCustomerProvider(&attacker, &as43284);
		g.InsertCustomerProvider(&as43284, &as13030);
		g.InsertPeerToPeer(&as13030, &victim);

		// Extend
		g.InsertCustomerProvider(&as13030_1, &as13030);
		g.InsertCustomerProvider(&as702_1, &as702);
		g.InsertCustomerProvider(&as702_2, &as702);
		g.InsertCustomerProvider(&as702_3, &as702);
		g.InsertCustomerProvider(&as702_4, &as702);

		orderedAss->push_back(&attacker);
		orderedAss->push_back(&victim);
		orderedAss->push_back(&as702);
		orderedAss->push_back(&as43284);
		orderedAss->push_back(&as13030);

		// Extend
		orderedAss->push_back(&as13030_1);
		orderedAss->push_back(&as702_1);
		orderedAss->push_back(&as702_2);
		orderedAss->push_back(&as702_3);
		orderedAss->push_back(&as702_4);

		g.InitializeOrderedAss(orderedAss);

// -------------

//  Prepare Attack
		Attack* attack = ExpliSatConverter::CreateAttractionAttack(&g, &victim, &attacker);
		attacker.TheAttack = attack;

// -------------

		//g.PrintGraph();
		g.RunBgp();
		//g.PrintSelectedaPaths();
		int effectivness = g.HowMuchTrafficThroughTheAttacker(&attacker, &victim);

		std::cout << "SPEA with connectivity- Number of paths to the victim(" << victim.GetName() << ") through the attacker(" << attacker.GetName() << ") is "
			<< effectivness << std::endl;
		// Expected Result = 5
	}
}

#include "formal.h"
void Test_ExpicitSatConverter()
{
	int speaEffectivness = 0;
	int nonDetEffectivness = 0;

	// SPEA
	{
		// G:
		//                 victim  -- |
		//                  |       13030
		//                  |         ^
		//                  702       |
		//                  ^       43284
		//                  |         ^
		//                 Attacker __|
		//
		//
		Topology g = Topology();
		Vector<As*>* orderedAss = new Vector<As*>();

		//  Prepare Vertices

		As victim = As(VICTIM_ID);
		As as702 = As(AS702_ID);
		As as43284 = As(AS43284_ID);
		As as13030 = As(AS13030_ID);
		AttackerAs attacker = AttackerAs();

		// Extend
		As as13030_1 = As(AS13030_1_ID);
		As as702_1 = As(AS702_1_ID);
		As as702_2 = As(AS702_2_ID);
		As as702_3 = As(AS702_3_ID);
		As as702_4 = As(AS702_4_ID);

		// -------------

		//  Prepare Edges

		g.InsertCustomerProvider(&attacker, &as702);
		g.InsertPeerToPeer(&as702, &victim);
		g.InsertCustomerProvider(&attacker, &as43284);
		g.InsertCustomerProvider(&as43284, &as13030);
		g.InsertPeerToPeer(&as13030, &victim);

		// Extend
		g.InsertCustomerProvider(&as13030_1, &as13030);
		g.InsertCustomerProvider(&as702_1, &as702);
		g.InsertCustomerProvider(&as702_2, &as702);
		g.InsertCustomerProvider(&as702_3, &as702);
		g.InsertCustomerProvider(&as702_4, &as702);

		orderedAss->push_back(&attacker);
		orderedAss->push_back(&victim);
		orderedAss->push_back(&as702);
		orderedAss->push_back(&as43284);
		orderedAss->push_back(&as13030);

		// Extend
		orderedAss->push_back(&as13030_1);
		orderedAss->push_back(&as702_1);
		orderedAss->push_back(&as702_2);
		orderedAss->push_back(&as702_3);
		orderedAss->push_back(&as702_4);

		g.InitializeOrderedAss(orderedAss);

		// -------------

		//  Prepare Attack
		Attack spea = SPEA(&g, &victim, &attacker);
		attacker.TheAttack = &spea;

		// -------------

		//g.PrintGraph();
		g.RunBgp();
		g.PrintSelectedaPaths();

		speaEffectivness = g.HowMuchTrafficThroughTheAttacker(&attacker, &victim);
	}

	// Non_det int attack
	{
		// G:
		//                 victim  -- |
		//                  |       13030
		//                  |         ^
		//                  702       |
		//                  ^       43284
		//                  |         ^
		//                 Attacker __|
		//
		//
		Topology g = Topology();
		Vector<As*>* orderedAss = new Vector<As*>();

		//  Prepare Vertices

		As victim = As(VICTIM_ID);
		As as702 = As(AS702_ID);
		As as43284 = As(AS43284_ID);
		As as13030 = As(AS13030_ID);
		AttackerAs attacker = AttackerAs();

		// Extend
		As as13030_1 = As(AS13030_1_ID);
		As as702_1 = As(AS702_1_ID);
		As as702_2 = As(AS702_2_ID);
		As as702_3 = As(AS702_3_ID);
		As as702_4 = As(AS702_4_ID);

		// -------------

		//  Prepare Edges

		g.InsertCustomerProvider(&attacker, &as702);
		g.InsertPeerToPeer(&as702, &victim);
		g.InsertCustomerProvider(&attacker, &as43284);
		g.InsertCustomerProvider(&as43284, &as13030);
		g.InsertPeerToPeer(&as13030, &victim);

		// Extend
		g.InsertCustomerProvider(&as13030_1, &as13030);
		g.InsertCustomerProvider(&as702_1, &as702);
		g.InsertCustomerProvider(&as702_2, &as702);
		g.InsertCustomerProvider(&as702_3, &as702);
		g.InsertCustomerProvider(&as702_4, &as702);

		orderedAss->push_back(&attacker);
		orderedAss->push_back(&victim);
		orderedAss->push_back(&as702);
		orderedAss->push_back(&as43284);
		orderedAss->push_back(&as13030);

		// Extend
		orderedAss->push_back(&as13030_1);
		orderedAss->push_back(&as702_1);
		orderedAss->push_back(&as702_2);
		orderedAss->push_back(&as702_3);
		orderedAss->push_back(&as702_4);

		g.InitializeOrderedAss(orderedAss);

		// -------------

		//  Prepare Attack
		Attack* attack = ExpliSatConverter::CreateAttractionAttack(&g, &victim, &attacker);
		attacker.TheAttack = attack;

		// -------------

		//g.PrintGraph();
		g.RunBgp();
		g.PrintSelectedaPaths();

		nonDetEffectivness = g.HowMuchTrafficThroughTheAttacker(&attacker, &victim);
	}

	fv_assert(nonDetEffectivness <= speaEffectivness);
}

void Test_NullifyTopology()
{

	// G:
	//                 victim  -- |
	//                  |       13030
	//                  |         ^
	//                  702       |
	//                  ^       43284
	//                  |         ^
	//                 Attacker __|
	//
	//
	Topology g = Topology();
	Vector<As*>* orderedAss = new Vector<As*>();

	//  Prepare Vertices

	As victim = As(VICTIM_ID);
	As as702 = As(AS702_ID);
	As as43284 = As(AS43284_ID);
	As as13030 = As(AS13030_ID);
	AttackerAs attacker = AttackerAs();

	// Extend
	As as13030_1 = As(AS13030_1_ID);
	As as702_1 = As(AS702_1_ID);
	As as702_2 = As(AS702_2_ID);
	As as702_3 = As(AS702_3_ID);
	As as702_4 = As(AS702_4_ID);

	// -------------

	//  Prepare Edges

	g.InsertCustomerProvider(&attacker, &as702);
	g.InsertPeerToPeer(&as702, &victim);
	g.InsertCustomerProvider(&attacker, &as43284);
	g.InsertCustomerProvider(&as43284, &as13030);
	g.InsertPeerToPeer(&as13030, &victim);

	// Extend
	g.InsertCustomerProvider(&as13030_1, &as13030);
	g.InsertCustomerProvider(&as702_1, &as702);
	g.InsertCustomerProvider(&as702_2, &as702);
	g.InsertCustomerProvider(&as702_3, &as702);
	g.InsertCustomerProvider(&as702_4, &as702);

	orderedAss->push_back(&attacker);
	orderedAss->push_back(&victim);
	orderedAss->push_back(&as702);
	orderedAss->push_back(&as43284);
	orderedAss->push_back(&as13030);

	// Extend
	orderedAss->push_back(&as13030_1);
	orderedAss->push_back(&as702_1);
	orderedAss->push_back(&as702_2);
	orderedAss->push_back(&as702_3);
	orderedAss->push_back(&as702_4);

	g.InitializeOrderedAss(orderedAss);

	// -------------


	////  SPEA
	//Attack spea = SPEA(&g, &victim, &attacker);
	//attacker.TheAttack = &spea;
	//g.RunBgp();
	//int speaEffectivness = g.HowMuchTrafficThroughTheAttacker(&attacker, &victim);

	//g.NullifyBgp();

	//  SpeaWithConnectivity
	SpeaWithConnectivity speaWithConnectivity = SpeaWithConnectivity(&g, &victim, &attacker);
	speaWithConnectivity.PrintAttack();
	attacker.TheAttack = &speaWithConnectivity;
	g.RunBgp();
	int speaWithConnectivityEffectivness = g.HowMuchTrafficThroughTheAttacker(&attacker, &victim);

	g.NullifyBgp();

	//  Non Det
	Attack* attack = ExpliSatConverter::CreateAttractionAttack(&g, &victim, &attacker);
	//fv_assume(attack->Msg->UpdatedPaths->begin()->second.size() != spea.Msg->UpdatedPaths->begin()->second.size());
	attacker.TheAttack = attack;
	attack->PrintAttack();
	g.RunBgp();
	g.PrintSelectedaPaths();
	int nonDetEffectivness = g.HowMuchTrafficThroughTheAttacker(&attacker, &victim);
	
	//fv_assert(nonDetEffectivness <= speaEffectivness);
	fv_assert(nonDetEffectivness <= speaWithConnectivityEffectivness);
}

#include <iostream>
void Test_DFS()
{
	Topology g = Topology();
	Vector<As*>* orderedAss = new Vector<As*>();

	//  Prepare Vertices
	As as1 = As(1);
	As as2 = As(2);
	As as3 = As(3);
	As as4 = As(4);
	As as5 = As(5);
	As as6 = As(6);
	As as7 = As(7);
	As as8 = As(8);

	//  Prepare Edges

	g.InsertCustomerProvider(&as1, &as2);
	g.InsertCustomerProvider(&as2, &as1);  // Makes no difference
	g.InsertCustomerProvider(&as1, &as4);
	g.InsertCustomerProvider(&as1, &as7);
	g.InsertCustomerProvider(&as2, &as4);
	g.InsertCustomerProvider(&as2, &as3);
	g.InsertCustomerProvider(&as3, &as5);
	g.InsertCustomerProvider(&as3, &as8);
	g.InsertCustomerProvider(&as4, &as5);
	g.InsertCustomerProvider(&as5, &as6);
	g.InsertCustomerProvider(&as5, &as7);
	g.InsertCustomerProvider(&as6, &as8);
	g.InsertCustomerProvider(&as7, &as8);

	Vector<Vertex*> visited;
	visited.push_back(&as2);
	Vector<Vector<As*>*>* dfsPaths = new Vector<Vector<As*>*>();
	ExpliSatConverter::DepthFirst(&g, visited, &as5, dfsPaths);
	
	std::cout << "DFS TEST " << std::endl;
	for (Vector<Vector<As*>*>::iterator node_it = dfsPaths->begin(); node_it != dfsPaths->end(); node_it++)
	{
		Vector<As*>* path = *node_it;
		for (Vector<As*>::iterator node_it_2 = path->begin(); node_it_2 != path->end(); node_it_2++)
		{
			As* node = *node_it_2;
			std::cout << node->_name << " ";
		}
		std::cout << std::endl;
	}
	std::cout << "DFS TEST DONE " << std::endl;
}

void Test_ExplisatConverterCreateTopology()
{
	As* victim = new As(VICTIM_ID);
	AttackerAs* attacker = new AttackerAs();
	Topology* g = ExpliSatConverter::CreateTopology(victim, attacker);

	//unsigned int topologySize = g->GetOrderedAssAfterInitialized()->size();
	//fv_assert(topologySize == 5);

	// -------------


	//  SPEA
	Attack spea = SPEA(g, victim, attacker);
	attacker->TheAttack = &spea;
	g->RunBgp();
	int speaEffectivness = g->HowMuchTrafficThroughTheAttacker(attacker, victim);

	g->NullifyBgp();

	////  SpeaWithConnectivity
	//SpeaWithConnectivity speaWithConnectivity = SpeaWithConnectivity(g, victim, attacker);
	//attacker->TheAttack = &speaWithConnectivity;
	//g->RunBgp();
	//int speaWithConnectivityEffectivness = g->HowMuchTrafficThroughTheAttacker(attacker, victim);
	//fv_assert(speaWithConnectivityEffectivness == 3);

	//g->NullifyBgp();

	//  Non Det
	Attack* attack = ExpliSatConverter::CreateAttractionAttack(g, victim, attacker);
	attacker->TheAttack = attack;
	g->RunBgp();
	g->PrintSelectedaPaths();
	int nonDetEffectivness = g->HowMuchTrafficThroughTheAttacker(attacker, victim);

	fv_assert(nonDetEffectivness <= speaEffectivness);
}

void Test_InterceptionAttack()
{

	// G:
	//                 victim  -- |
	//                  |       13030
	//                  |         ^
	//                  702       |
	//                  ^       43284
	//                  |         ^
	//                 Attacker __|
	//
	//
	Topology g = Topology();
	Vector<As*>* orderedAss = new Vector<As*>();

	//  Prepare Vertices

	As victim = As(VICTIM_ID);
	As as702 = As(AS702_ID);
	As as43284 = As(AS43284_ID);
	As as13030 = As(AS13030_ID);
	AttackerAs attacker = AttackerAs();

	// Extend
	As as13030_1 = As(AS13030_1_ID);
	As as702_1 = As(AS702_1_ID);
	As as702_2 = As(AS702_2_ID);
	As as702_3 = As(AS702_3_ID);
	As as702_4 = As(AS702_4_ID);

	// -------------

	//  Prepare Edges

	g.InsertCustomerProvider(&attacker, &as702);
	g.InsertPeerToPeer(&as702, &victim);
	g.InsertCustomerProvider(&attacker, &as43284);
	g.InsertCustomerProvider(&as43284, &as13030);
	g.InsertPeerToPeer(&as13030, &victim);

	// Extend
	g.InsertCustomerProvider(&as13030_1, &as13030);
	g.InsertCustomerProvider(&as702_1, &as702);
	g.InsertCustomerProvider(&as702_2, &as702);
	g.InsertCustomerProvider(&as702_3, &as702);
	g.InsertCustomerProvider(&as702_4, &as702);

	orderedAss->push_back(&attacker);
	orderedAss->push_back(&victim);
	orderedAss->push_back(&as702);
	orderedAss->push_back(&as43284);
	orderedAss->push_back(&as13030);

	// Extend
	orderedAss->push_back(&as13030_1);
	orderedAss->push_back(&as702_1);
	orderedAss->push_back(&as702_2);
	orderedAss->push_back(&as702_3);
	orderedAss->push_back(&as702_4);

	g.InitializeOrderedAss(orderedAss);

	// -------------


	////  SPEA
	//Attack spea = SPEA(&g, &victim, &attacker);
	//attacker.TheAttack = &spea;
	//g.RunBgp();
	//int speaEffectivness = g.HowMuchTrafficThroughTheAttacker(&attacker, &victim);

	//g.NullifyBgp();

	//  SpeaWithConnectivity
	SpeaWithConnectivity speaWithConnectivity = SpeaWithConnectivity(&g, &victim, &attacker);
	speaWithConnectivity.PrintAttack();
	attacker.TheAttack = &speaWithConnectivity;
	g.RunBgp();
	int speaWithConnectivityEffectivness = g.HowMuchTrafficThroughTheAttacker(&attacker, &victim);

	g.NullifyBgp();

	//  Non Det
	Attack* attack = ExpliSatConverter::CreateInterceptionAttack(&g, &victim, &attacker);
	//fv_assume(attack->Msg->UpdatedPaths->begin()->second.size() != spea.Msg->UpdatedPaths->begin()->second.size());
	attacker.TheAttack = attack;
	attack->PrintAttack();
	g.RunBgp();
	//g.PrintSelectedaPaths();
	int nonDetEffectivness = g.HowMuchTrafficThroughTheAttacker(&attacker, &victim);

	//fv_assert(nonDetEffectivness <= speaEffectivness);
	fv_assert(nonDetEffectivness <= speaWithConnectivityEffectivness);
}

void Test_InterceptionAttackOnNonDetTopology()
{

	As* victim = new As(VICTIM_ID);
	AttackerAs* attacker = new AttackerAs();
	Topology* g = ExpliSatConverter::CreateTopology(victim, attacker);

	// -------------


	////  SPEA
	//Attack spea = SPEA(&g, &victim, &attacker);
	//attacker.TheAttack = &spea;
	//g.RunBgp();
	//int speaEffectivness = g.HowMuchTrafficThroughTheAttacker(&attacker, &victim);

	//g.NullifyBgp();

	//  SpeaWithConnectivity
	SpeaWithConnectivity speaWithConnectivity = SpeaWithConnectivity(g, victim, attacker);
	speaWithConnectivity.PrintAttack();
	attacker->TheAttack = &speaWithConnectivity;
	g->RunBgp();
	int speaWithConnectivityEffectivness = g->HowMuchTrafficThroughTheAttacker(attacker, victim);

	g->NullifyBgp();

	//  Non Det
	Attack* attack = ExpliSatConverter::CreateInterceptionAttack(g, victim, attacker);
	//fv_assume(attack->Msg->UpdatedPaths->begin()->second.size() != spea.Msg->UpdatedPaths->begin()->second.size());
	attacker->TheAttack = attack;
	attack->PrintAttack();
	g->RunBgp();
	//g.PrintSelectedaPaths();
	int nonDetEffectivness = g->HowMuchTrafficThroughTheAttacker(attacker, victim);

	//fv_assert(nonDetEffectivness <= speaEffectivness);
	fv_assert(nonDetEffectivness <= speaWithConnectivityEffectivness);
}

void Test_GaminLoopsAttack()
{

	// G:
	//                 victim  -- |
	//                  |       13030
	//                  |         ^
	//                  702       |
	//                  ^       43284
	//                  |         ^
	//                 Attacker __|
	//
	//
	Topology g = Topology();
	Vector<As*>* orderedAss = new Vector<As*>();

	//  Prepare Vertices

	As victim = As(VICTIM_ID); // 745
	AttackerAs attacker = AttackerAs();
	As as25653 = As(AS25653_ID);
	As as4436 = As(AS4436_ID);
	As as852 = As(AS852_ID);
	As as3561 = As(AS3561_ID);
	As as209 = As(AS209_ID);
	As as721 = As(AS721_ID);
	As as27064 = As(AS27064_ID);
	As as27085 = As(AS27085_ID);
	
	// Extend
	As as3561_1 = As(AS3561_1_ID);
	As as3561_2 = As(AS3561_2_ID);
	As as3561_3 = As(AS3561_3_ID);
	As as3561_4 = As(AS3561_4_ID);

	// -------------

	//  Prepare Edges

	g.InsertCustomerProvider(&victim, &as27085);
	g.InsertCustomerProvider(&as27085, &as27064);
	g.InsertCustomerProvider(&as27064, &as721);
	g.InsertCustomerProvider(&as721, &as209);

	g.InsertPeerToPeer(&as209, &as3561);

	g.InsertPeerToPeer(&as3561, &as25653);

	g.InsertCustomerProvider(&as852, &as3561);
	g.InsertCustomerProvider(&as4436, &as852);
	g.InsertCustomerProvider(&as25653, &as4436);
	g.InsertCustomerProvider(&attacker, &as25653);


	// Extend
	g.InsertCustomerProvider(&as3561_1, &as3561);
	g.InsertCustomerProvider(&as3561_2, &as3561);
	g.InsertCustomerProvider(&as3561_3, &as3561);
	g.InsertCustomerProvider(&as3561_4, &as3561);

	g.InsertCustomerProvider(&as3561_1, &as209);
	g.InsertCustomerProvider(&as3561_2, &as209);
	g.InsertCustomerProvider(&as3561_3, &as209);
	g.InsertCustomerProvider(&as3561_4, &as209);

	orderedAss->push_back(&attacker);
	orderedAss->push_back(&victim);
	orderedAss->push_back(&as25653);
	orderedAss->push_back(&as4436);
	orderedAss->push_back(&as852);
	orderedAss->push_back(&as3561);
	orderedAss->push_back(&as209);
	orderedAss->push_back(&as721);
	orderedAss->push_back(&as27064);
	orderedAss->push_back(&as27085);

	// Extend
	orderedAss->push_back(&as3561_1);
	orderedAss->push_back(&as3561_2);
	orderedAss->push_back(&as3561_3);
	orderedAss->push_back(&as3561_4);

	g.InitializeOrderedAss(orderedAss);

	// -------------

	//  SPEA
	Attack spea = SPEA(&g, &victim, &attacker);
	attacker.TheAttack = &spea;
	g.RunBgp();
	int speaEffectivness = g.HowMuchTrafficThroughTheAttacker(&attacker, &victim);

	g.PrintSelectedaPaths();
	g.NullifyBgp();

	////  Non Det
	//Attack* attack = ExpliSatConverter::CreateInterceptionAttack(&g, &victim, &attacker);
	////fv_assume(attack->Msg->UpdatedPaths->begin()->second.size() != spea.Msg->UpdatedPaths->begin()->second.size());
	//attacker.TheAttack = attack;
	//attack->PrintAttack();
	//g.RunBgp();
	////g.PrintSelectedaPaths();
	//int nonDetEffectivness = g.HowMuchTrafficThroughTheAttacker(&attacker, &victim);

	////fv_assert(nonDetEffectivness <= speaEffectivness);
	//fv_assert(nonDetEffectivness <= speaWithConnectivityEffectivness);
}


// AS0 = The Attacker
// AS1= The Victim
int main() {
	//std::cout << "!!!Hello World!!!" << std::endl; // prints !!!Hello World!!!
	//TestProviderAndThenCustomer();
	//TestCustomerAndThenProvider();

	//TestBgpRunWithTwoAss();
	//TestBgpRunWithThreeAss();
	//TestBgpRunWithProviderAndConsumerPaths();

	//TestBgpWithoutAttacks();
	//TestBgpWithSPEA_2Ass();
	//TestBgpWithSPEA_SmallestNetwork_3ass();
	//TestBgpWithSPEA_TopologyThatItIsEffective();

	//TestSPEAConnectivity_ShortersPathTest();

	// Smart Attacks
	//TestBgpWithSPEA_SmartTopologyAnnounceLongerPaths();
	//TestBgpWithSpeaWithConnectivity_SmartTopologyAnnounceLongerPaths();

	//Test_ExpicitSatConverter();
	//Test_NullifyTopology();
	
	//Test_ExplisatConverterCreateTopology();
	
	//Test_DFS();

	//Test_InterceptionAttack();
	Test_InterceptionAttackOnNonDetTopology();

	//Test_GaminLoopsAttack();
	//system("PAUSE");
	return 0;
}
